package org.example.paymentservice.service.impl;

import lombok.RequiredArgsConstructor;
import org.example.paymentservice.dto.RefundRequest;
import org.example.paymentservice.entity.Order;
import org.example.paymentservice.entity.PaymentTransaction;
import org.example.paymentservice.repository.PaymentTransactionRepository;
import org.example.paymentservice.service.OrderProcessor;
import org.example.paymentservice.service.RefundHandler;
import org.example.paymentservice.service.provider.PaymentProviderFactory;
import org.example.paymentservice.service.provider.PaymentProvider;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class RefundHandlerImpl implements RefundHandler {
    private final OrderProcessor orderProcessor;
    private final PaymentTransactionRepository transactionRepository;
    private final PaymentProviderFactory paymentProviderFactory;

    @Override
    @Transactional
    public PaymentTransaction processRefund(RefundRequest refundRequest) {
        Order order = orderProcessor.getOrder(refundRequest.getOrderId());
        
        if (order.getStatus() != Order.PaymentStatus.PAID) {
            throw new IllegalStateException("Order is not in PAID status");
        }

        PaymentProvider provider = paymentProviderFactory.getProvider(order.getPaymentMethod());

        PaymentTransaction transaction = new PaymentTransaction();
        transaction.setOrder(order);
        transaction.setAmount(refundRequest.getAmount());
        transaction.setType(PaymentTransaction.TransactionType.REFUND);
        transaction.setPaymentProvider(order.getPaymentMethod().toString());

        try {
            String refundId = provider.processRefund(
                    order.getTransactionId(),
                    refundRequest.getAmount(),
                    refundRequest.getReason()
            );

            transaction.setProviderTransactionId(refundId);
            transaction.setStatus(PaymentTransaction.TransactionStatus.SUCCESS);
            orderProcessor.updateOrderStatus(order.getId(), Order.PaymentStatus.REFUNDED);
        } catch (Exception e) {
            transaction.setStatus(PaymentTransaction.TransactionStatus.FAILED);
            transaction.setErrorMessage(e.getMessage());
        }

        return transactionRepository.save(transaction);
    }

    @Override
    public PaymentTransaction getRefundDetails(String refundId) {
        return transactionRepository.findByProviderTransactionId(refundId)
                .orElseThrow(() -> new EntityNotFoundException("Refund transaction not found"));
    }
}